package world.snowcrystal.aa;

import jakarta.annotation.Nonnull;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.log4j.Log4j2;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseCookie;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.stereotype.Component;
import world.snowcrystal.event.LogoutSuccessWithContextEvent;
import world.snowcrystal.properties.AuthenticationProperties;


@Log4j2
@Component
public class DefaultLogoutHandler implements LogoutHandler, ApplicationEventPublisherAware {

    private ApplicationEventPublisher eventPublisher;

    private AuthenticationProperties properties;

    public DefaultLogoutHandler(AuthenticationProperties properties) {
        this.properties = properties;
    }

    /**
     * Causes a logout to be completed. The method must complete successfully.
     *
     * @param request        the HTTP request
     * @param response       the HTTP response
     * @param authentication the current principal details
     */
    @Override
    public void logout(HttpServletRequest request,
                       HttpServletResponse response,
                       Authentication authentication) {
        if (authentication != null) {
            String username = authentication.getPrincipal().toString();
            log.info("user {} has been logged out", username);
        } else {
            log.info("user from {} has been logged out", request.getRemoteAddr());
        }
        final ResponseCookie build = ResponseCookie.from(properties.getRememberMeCookieName())
                .secure(true)
                .maxAge(0L)
                .path("/")
                .domain(properties.getCookieDomain())
                .build();
        response.setHeader(HttpHeaders.SET_COOKIE, build.toString());
        final Cookie[] cookies = request.getCookies();
        String fp = "";
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if ("fingerprint".equals(cookie.getName())) {
                    fp = cookie.getValue();
                }
            }
        }
        if (authentication != null) {
            var e = new LogoutSuccessWithContextEvent(authentication);
            e.setFingerprint(fp);
            eventPublisher.publishEvent(e);
        }
    }


    /**
     * Set the ApplicationEventPublisher that this object runs in.
     * <p>Invoked after population of normal bean properties but before an init
     * callback like InitializingBean's afterPropertiesSet or a custom init-method.
     * Invoked before ApplicationContextAware's setApplicationContext.
     *
     * @param applicationEventPublisher event publisher to be used by this object
     */
    @Override
    public void setApplicationEventPublisher(@Nonnull ApplicationEventPublisher applicationEventPublisher) {
        this.eventPublisher = applicationEventPublisher;
    }
}
